Imports System.IO
Imports System.Xml
Imports System.Xml.Serialization

Public Class frmManagePens

    Public srchPen As PenData
    Public penList As List(Of PenData)

    Private Sub btnMoveUp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMoveUp.Click

    End Sub

    Private Sub lstPens_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstPens.SelectedIndexChanged

    End Sub

    Private Sub mnuExport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuExport.Click
        Dim curPen As PenData = Nothing

        'ensure a pen is selected
        If lstPens.SelectedItem Is Nothing Then
            System.Windows.Forms.MessageBox.Show("No pen selected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Exit Sub
        End If
        'ensure pen is in list (bad if not)
        curPen = GetPen(CType(lstPens.SelectedItem, String))
        If curPen Is Nothing Then
            System.Windows.Forms.MessageBox.Show("CRITICAL ERROR" + vbCrLf + "Failed to find pen in internal list.  A restart of the toolset is" + vbCrLf + "recommended.  If this problem continues, let Languard know", "Critical Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Exit Sub
        End If

        'put in a list since that's what DoXmlExport needs
        Dim pens As List(Of PenData) = New List(Of PenData)
        pens.Add(curPen)
        DoXmlExport(pens)
    End Sub

    Private Sub DoXmlExport(ByVal pens As List(Of PenData))
        Dim xmlOut As XmlSerializer
        Dim pathPrefix As String
        Dim fname As String
        Dim path As String
        Dim fs As FileStream = Nothing
        Dim fs2 As FileStream = Nothing
        Dim xWriter As XmlTextWriter = Nothing   'the nothing sushes the compiler complaining about the finally block
        Dim tWriter As StreamWriter = Nothing

        Try
            xmlOut = New XmlSerializer(GetType(PenData))

            pathPrefix = Application.StartupPath + "\NWN2Toolset\PenData"

            If Not System.IO.Directory.Exists(pathPrefix) Then
                Directory.CreateDirectory(pathPrefix)
            End If

            'check to see if this is a group
            If pens.Count > 1 Then
                Dim groupName As frmGetString = New frmGetString
                groupName.Text = "Pen Group Name"
                groupName.ShowDialog()
                If groupName.DialogResult = Windows.Forms.DialogResult.Cancel Then
                    Windows.Forms.MessageBox.Show("Export Cancelled")
                    Exit Sub
                Else
                    Try
                        fs2 = New FileStream(pathPrefix + "\" + groupName.Result + ".txt", FileMode.Create)
                        tWriter = New StreamWriter(fs2)
                    Catch ex As Exception
                        Windows.Forms.MessageBox.Show("Failed to create group file, aborting export" + vbCrLf + ex.Message)
                        Exit Sub
                    End Try
                End If
            End If

            For Each curPen As PenData In pens
                'flag the pen as exporting
                curPen.IsExporting = True
                'if this is a group export, write the pen name to the group list
                If Not fs2 Is Nothing Then
                    If Not curPen.Name.StartsWith("Default") Then
                        tWriter.WriteLine(curPen.Name + ".xml")
                    End If
                End If
                'and write the pen to xml
                If Not curPen.Name.StartsWith("Default") Then
                    fname = curPen.Name + ".xml"
                    path = pathPrefix + "\" + fname
                    fs = New FileStream(path, FileMode.Create)
                    xWriter = New XmlTextWriter(fs, System.Text.Encoding.UTF8)
                    xWriter.Formatting = Formatting.Indented
                    xmlOut.Serialize(xWriter, curPen)
                    xWriter.Flush()
                    xWriter.Close()
                End If
                'remove exporting flag
                curPen.IsExporting = False
            Next

            'close out group stream if needed
            If Not fs2 Is Nothing Then
                tWriter.Flush()
                tWriter.Close()
            End If


        Catch ioE As IOException
            System.Windows.Forms.MessageBox.Show("An exception occured during IO operations:" & vbCrLf & ioE.Message)
        Catch xmlE As XmlException
            System.Windows.Forms.MessageBox.Show("An exception occured during XML operations:" & vbCrLf & xmlE.Message)
        Catch genE As Exception
            If genE.InnerException Is Nothing Then
                System.Windows.Forms.MessageBox.Show("An general exception occured" & vbCrLf & genE.Message)
            Else
                System.Windows.Forms.MessageBox.Show("An general exception occured" & vbCrLf & genE.Message & vbCrLf & "Inner: " + genE.InnerException.Message)
            End If
        Finally
            If Not (xWriter Is Nothing) Then
                xWriter.Close()
                'Windows.Forms.MessageBox.Show("Export Complete")
            End If
        End Try

    End Sub

    Private Sub DoXmlImport(ByVal fnames As List(Of String))
        Dim ser As XmlSerializer = New XmlSerializer(GetType(PenData))
        Dim curPen As PenData = Nothing
        Dim tmpPen As PenData = Nothing
        Dim fs As FileStream = Nothing
        Dim pathPrefix As String
        'Dim path As String
        'Dim startIndex As Integer
        'Dim length As Integer

        pathPrefix = Application.StartupPath + "\NWN2Toolset\PenData"

        For Each curName As String In fnames
            
            'open and deserialize
            Try
                'path = pathPrefix + "\" + curName
                fs = New FileStream(curName, FileMode.Open)
                curPen = ser.Deserialize(fs)
                'check for and remove duplicates
                If FindPenName(curPen.Name) Then
                    tmpPen = GetPen(curPen.Name)                    
                    penList.Remove(tmpPen)
                End If
                'never allow Nib/Eraser to be imported in
                curPen.IsNib = False
                curPen.IsEraser = False
                penList.Add(curPen)
            Catch err As Exception
                If err.InnerException Is Nothing Then
                    Windows.Forms.MessageBox.Show("Failed to deserialize" + vbCrLf + err.Message)
                Else
                    Windows.Forms.MessageBox.Show("Failed to deserialize" + vbCrLf + err.Message + vbCrLf + "Inner: " + err.InnerException.Message)
                End If
            Finally
                If Not fs Is Nothing Then
                    fs.Close()
                    'Windows.Forms.MessageBox.Show("Import Complete")
                End If
            End Try

        Next

        'make sure list box is updated
        Me.UpdateControl()


    End Sub

    Private Sub btnCreateNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreateNew.Click
        Dim temp As New PenData
        Dim count As Integer
        count = 0
        While FindPenName("New Pen" + count.ToString("d2"))
            count += 1
        End While

        temp.Name = "New Pen" + count.ToString("d2")
        penList.Add(temp)
        lstPens.Items.Add(temp.Name)
    End Sub

    Private Function FindPenName(ByVal target As String) As Boolean
        Dim result As Boolean
        result = False

        For Each srchPen In penList
            If srchPen.Name = target Then
                result = True
                Exit For
            End If
        Next
        Return result
    End Function

    Public Sub SetPenList(ByRef plist As List(Of PenData))
        penList = plist
        lstPens.Items.Clear()

        'populate list
        For Each srchPen In penList
            lstPens.Items.Add(srchPen.Name)
        Next
    End Sub

    Public Sub UpdateControl()
        lstPens.Items.Clear()

        'populate list
        For Each srchPen In penList
            lstPens.Items.Add(srchPen.ToString)
        Next
    End Sub

    Private Sub frmManagePens_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub mnuImport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuImport.Click

        'bring up a load file dialog set to xml
        dialogLoadPens.Filter = "XML Files|*.xml"
        dialogLoadPens.Title = "Choose a Pen xml file to import"
        dialogLoadPens.InitialDirectory = Application.StartupPath + "\NWN2Toolset\PenData"

        If Not (dialogLoadPens.ShowDialog() = Windows.Forms.DialogResult.Cancel) Then
            'construct a single element list and pass it in to DoXmlImport
            Dim x As String
            Dim fname As List(Of String) = New List(Of String)
            x = dialogLoadPens.FileName
            fname.Add(x)
            DoXmlImport(fname)
        End If


    End Sub

    Public Function GetPen(ByVal name As String) As PenData
        Dim result As PenData = Nothing

        For Each curPen As PenData In penList
            If curPen.Name = name Then
                result = curPen
                Exit For
            End If
        Next

        Return result
    End Function

    Private Sub ExportPenGroupToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExportPenGroupToolStripMenuItem.Click
        Dim pens As List(Of PenData) = New List(Of PenData)

        'build the pen list, excluding default
        For Each curPen As PenData In penList
            If Not curPen.Name.StartsWith("Default") Then
                pens.Add(curPen)
            End If
        Next

        DoXmlExport(pens)
    End Sub

    Private Sub btnClearAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClearAll.Click
        'clear all pens out of the list except the defaults
        Dim defNib As PenData
        Dim defErase As PenData

        defNib = penList(0)
        defErase = penList(1)
        penList.Clear()
        penList.Add(defNib)
        penList.Add(defErase)
        UpdateControl()

    End Sub

    Private Sub ImportPenGroupToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ImportPenGroupToolStripMenuItem.Click
        Dim fs As FileStream = Nothing
        Dim tRead As StreamReader = Nothing
        Dim names As List(Of String) = Nothing
        Dim curName As String

        'get the group file to open
        dialogLoadPens.Title = "Choose group file"
        dialogLoadPens.Filter = "Group Files|*.txt"
        dialogLoadPens.InitialDirectory = Application.StartupPath + "\NWN2Toolset\PenData"

        If Not dialogLoadPens.ShowDialog = Windows.Forms.DialogResult.Cancel Then
            Try
                tRead = New StreamReader(dialogLoadPens.FileName)
                names = New List(Of String)

                'read out all names
                Do While tRead.Peek <> -1
                    curName = tRead.ReadLine
                    curName = Application.StartupPath + "\NWN2Toolset\Pendata\" + curName
                    names.Add(curName)
                Loop
            Catch ex As Exception
                If ex.InnerException Is Nothing Then
                    Windows.Forms.MessageBox.Show("Failed to read the group file" + vbCrLf + ex.Message)
                Else
                    Windows.Forms.MessageBox.Show("Failed to read the group file" + vbCrLf + ex.Message + vbCrLf + "Inner: " + ex.InnerException.Message)
                End If
            Finally
                If Not tRead Is Nothing Then
                    tRead.Close()
                End If
            End Try
        End If

        'if the list isn't null, do the import
        If Not names Is Nothing Then
            DoXmlImport(names)
        End If
    End Sub

    Private Sub btnCreateCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreateCopy.Click
        Dim target As PenData = Nothing
        Dim copy As PenData = Nothing
        Dim count As Integer = 1

        'ensure a pen is selected
        target = GetPen(lstPens.SelectedItem)
        If target Is Nothing Then
            Windows.Forms.MessageBox.Show("No pen selected", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            Exit Sub
        End If

        'make a copy
        copy = New PenData(target)
        'alter the name
        While FindPenName(copy.Name + " Copy" + count.ToString("d2"))
            count += 1
        End While
        copy.Name = copy.Name + " Copy" + count.ToString("d2")
        'add new pen to list
        penList.Add(copy)
        'update control
        UpdateControl()
    End Sub

    Private Sub btnRename_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRename.Click
        Dim target As PenData = Nothing
        Dim newName As String = ""

        'make sure a pen is selected
        target = GetPen(lstPens.SelectedItem)
        If target Is Nothing Then
            Windows.Forms.MessageBox.Show("No pen selected", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            Exit Sub
        End If

        'alter the name
        Dim getname As frmGetString = New frmGetString
        getname.Text = "Enter new pen name"
        If Not getname.ShowDialog = Windows.Forms.DialogResult.Cancel Then
            newName = getname.Result
            target.Name = newName
        Else
            Exit Sub
        End If
        'update control
        UpdateControl()
    End Sub

    Private Sub btnDeleteCurrent_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDeleteCurrent.Click
        Dim target As PenData = Nothing

        'make sure a pen is selected
        target = GetPen(lstPens.SelectedItem)
        If target Is Nothing Then
            Windows.Forms.MessageBox.Show("No pen selected", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            Exit Sub
        End If

        'make sure the pen isn't default
        If target.IsDefault Then
            Windows.Forms.MessageBox.Show("Can't delete default pens", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            Exit Sub
        End If

        'remove pen
        penList.Remove(target)
        'update control
        UpdateControl()
    End Sub
End Class